#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""规则匹配服务"""

import re
import logging
from typing import List, Dict, Any, Optional

from app.models.pdf_models import TableData, TableRule

# 创建日志记录器
logger = logging.getLogger(__name__)

class RuleService:
    """规则匹配服务，用于识别和处理不同类型的税务表格"""
    
    def __init__(self):
        """初始化规则服务"""
        # 预定义的规则集
        self.rules = self._initialize_rules()
    
    def _initialize_rules(self) -> List[TableRule]:
        """初始化预定义规则
        
        Returns:
            规则列表
        """
        rules = [
            # 增值税纳税申报表
            TableRule(
                id="vat_declaration",
                name="增值税纳税申报表",
                description="增值税纳税申报表主表",
                match_patterns=["增值税纳税申报表", "一般纳税人"],
                exclude_patterns=["附列资料", "减免税"],
                required_headers=["项目", "栏次", "本期数据", "累计数据"],
                min_columns=4,
                min_rows=5,
                data_type="tax_declaration"
            ),
            
            # 增值税纳税申报表附列资料
            TableRule(
                id="vat_declaration_attachment",
                name="增值税纳税申报表附列资料",
                description="增值税纳税申报表附列资料",
                match_patterns=["增值税纳税申报表附列资料"],
                exclude_patterns=[],
                required_headers=["项目", "栏次"],
                min_columns=3,
                min_rows=3,
                data_type="tax_declaration_attachment"
            ),
            
            # 企业所得税月(季)度预缴纳税申报表
            TableRule(
                id="income_tax_prepayment",
                name="企业所得税月(季)度预缴纳税申报表",
                description="企业所得税月(季)度预缴纳税申报表",
                match_patterns=["企业所得税", "预缴纳税申报表"],
                exclude_patterns=["年度纳税申报表"],
                required_headers=["项目", "金额"],
                min_columns=2,
                min_rows=5,
                data_type="income_tax_prepayment"
            ),
            
            # 企业所得税年度纳税申报表
            TableRule(
                id="income_tax_annual",
                name="企业所得税年度纳税申报表",
                description="企业所得税年度纳税申报表",
                match_patterns=["企业所得税", "年度纳税申报表"],
                exclude_patterns=["预缴纳税申报表"],
                required_headers=["项目", "金额"],
                min_columns=2,
                min_rows=10,
                data_type="income_tax_annual"
            ),
            
            # 资产负债表
            TableRule(
                id="balance_sheet",
                name="资产负债表",
                description="企业资产负债表",
                match_patterns=["资产负债表"],
                exclude_patterns=["利润表", "现金流量表"],
                required_headers=["资产", "负债和所有者权益"],
                min_columns=3,
                min_rows=10,
                data_type="financial_statement"
            ),
            
            # 利润表
            TableRule(
                id="income_statement",
                name="利润表",
                description="企业利润表",
                match_patterns=["利润表"],
                exclude_patterns=["资产负债表", "现金流量表"],
                required_headers=["项目", "本期金额"],
                min_columns=2,
                min_rows=10,
                data_type="financial_statement"
            ),
            
            # 现金流量表
            TableRule(
                id="cash_flow_statement",
                name="现金流量表",
                description="企业现金流量表",
                match_patterns=["现金流量表"],
                exclude_patterns=["资产负债表", "利润表"],
                required_headers=["项目", "金额"],
                min_columns=2,
                min_rows=10,
                data_type="financial_statement"
            ),
        ]
        
        return rules
    
    def match_table_rules(self, table_data: TableData) -> List[TableRule]:
        """匹配表格规则
        
        Args:
            table_data: 表格数据
            
        Returns:
            匹配的规则列表
        """
        matched_rules = []
        
        # 如果表格为空，返回空列表
        if not table_data or not table_data.data or len(table_data.data) == 0:
            return matched_rules
        
        # 提取表格标题和内容文本
        title = table_data.title or ""
        content_text = self._extract_table_text(table_data.data)
        
        # 检查每个规则
        for rule in self.rules:
            # 检查表格维度
            if table_data.rows < rule.min_rows or table_data.cols < rule.min_columns:
                continue
            
            # 检查匹配模式
            pattern_matched = False
            for pattern in rule.match_patterns:
                if pattern in title or pattern in content_text:
                    pattern_matched = True
                    break
            
            if not pattern_matched:
                continue
            
            # 检查排除模式
            exclude_matched = False
            for pattern in rule.exclude_patterns:
                if pattern in title or pattern in content_text:
                    exclude_matched = True
                    break
            
            if exclude_matched:
                continue
            
            # 检查必需的表头
            if rule.required_headers and table_data.headers:
                headers_matched = True
                headers_text = " ".join([str(h) for h in table_data.headers if h])
                
                for required_header in rule.required_headers:
                    if required_header not in headers_text:
                        headers_matched = False
                        break
                
                if not headers_matched:
                    continue
            
            # 所有条件都满足，添加到匹配规则列表
            matched_rules.append(rule)
        
        return matched_rules
    
    def process_table_by_rule(self, table_data: TableData, rule: TableRule) -> Dict[str, Any]:
        """根据规则处理表格数据
        
        Args:
            table_data: 表格数据
            rule: 匹配的规则
            
        Returns:
            处理后的数据
        """
        result = {
            "rule_id": rule.id,
            "rule_name": rule.name,
            "data_type": rule.data_type,
            "table_id": table_data.id,
            "processed_data": {}
        }
        
        # 根据不同的规则类型进行处理
        if rule.id == "vat_declaration":
            result["processed_data"] = self._process_vat_declaration(table_data)
        elif rule.id == "income_tax_prepayment":
            result["processed_data"] = self._process_income_tax_prepayment(table_data)
        elif rule.id == "balance_sheet":
            result["processed_data"] = self._process_balance_sheet(table_data)
        elif rule.id == "income_statement":
            result["processed_data"] = self._process_income_statement(table_data)
        else:
            # 默认处理：转换为键值对
            result["processed_data"] = self._convert_table_to_key_value(table_data)
        
        return result
    
    def _extract_table_text(self, table_data: List[List[Any]]) -> str:
        """提取表格文本内容
        
        Args:
            table_data: 表格数据
            
        Returns:
            表格文本内容
        """
        if not table_data:
            return ""
        
        text = ""
        for row in table_data:
            for cell in row:
                if cell:
                    text += str(cell) + " "
        
        return text
    
    def _convert_table_to_key_value(self, table_data: TableData) -> Dict[str, Any]:
        """将表格转换为键值对
        
        Args:
            table_data: 表格数据
            
        Returns:
            键值对数据
        """
        result = {}
        
        if not table_data or not table_data.data or len(table_data.data) < 2:
            return result
        
        # 检查表格结构
        if len(table_data.data[0]) >= 2:
            # 假设第一列是键，第二列是值
            for row in table_data.data:
                if len(row) >= 2 and row[0]:
                    key = str(row[0]).strip()
                    value = str(row[1]).strip() if row[1] else ""
                    
                    # 跳过表头或空键
                    if key and key != "项目" and key != "栏次":
                        # 处理数值
                        if re.match(r'^-?\d+(\.\d+)?$', value):
                            try:
                                value = float(value)
                            except ValueError:
                                pass
                        
                        result[key] = value
        
        return result
    
    def _process_vat_declaration(self, table_data: TableData) -> Dict[str, Any]:
        """处理增值税纳税申报表
        
        Args:
            table_data: 表格数据
            
        Returns:
            处理后的数据
        """
        result = {}
        
        if not table_data or not table_data.data:
            return result
        
        # 查找关键字段
        key_fields = [
            "销售额",
            "销项税额",
            "进项税额",
            "应纳税额",
            "实际应纳税额",
            "期末留抵税额"
        ]
        
        # 提取数据
        for row in table_data.data:
            if len(row) >= 3:  # 项目、栏次、本期数据
                item = str(row[0]).strip() if row[0] else ""
                
                # 查找关键字段
                for field in key_fields:
                    if field in item:
                        # 提取本期数据
                        current_value = str(row[2]).strip() if len(row) > 2 and row[2] else "0"
                        # 提取累计数据（如果有）
                        accumulated_value = str(row[3]).strip() if len(row) > 3 and row[3] else "0"
                        
                        # 转换为数值
                        try:
                            current_value = float(current_value)
                        except ValueError:
                            current_value = 0
                            
                        try:
                            accumulated_value = float(accumulated_value)
                        except ValueError:
                            accumulated_value = 0
                        
                        # 存储数据
                        result[field] = {
                            "current": current_value,
                            "accumulated": accumulated_value
                        }
                        break
        
        return result
    
    def _process_income_tax_prepayment(self, table_data: TableData) -> Dict[str, Any]:
        """处理企业所得税月(季)度预缴纳税申报表
        
        Args:
            table_data: 表格数据
            
        Returns:
            处理后的数据
        """
        result = {}
        
        if not table_data or not table_data.data:
            return result
        
        # 查找关键字段
        key_fields = [
            "收入总额",
            "不征税收入",
            "免税收入",
            "应纳税所得额",
            "税率",
            "应纳所得税额",
            "减免所得税额",
            "应纳所得税额合计"
        ]
        
        # 提取数据
        for row in table_data.data:
            if len(row) >= 2:  # 项目、金额
                item = str(row[0]).strip() if row[0] else ""
                
                # 查找关键字段
                for field in key_fields:
                    if field in item:
                        # 提取金额
                        value = str(row[1]).strip() if len(row) > 1 and row[1] else "0"
                        
                        # 转换为数值
                        try:
                            value = float(value)
                        except ValueError:
                            value = 0
                        
                        # 存储数据
                        result[field] = value
                        break
        
        return result
    
    def _process_balance_sheet(self, table_data: TableData) -> Dict[str, Any]:
        """处理资产负债表
        
        Args:
            table_data: 表格数据
            
        Returns:
            处理后的数据
        """
        result = {
            "assets": {},
            "liabilities": {},
            "equity": {}
        }
        
        if not table_data or not table_data.data:
            return result
        
        # 资产类关键字段
        asset_fields = [
            "货币资金",
            "应收账款",
            "存货",
            "固定资产",
            "无形资产",
            "资产总计"
        ]
        
        # 负债类关键字段
        liability_fields = [
            "短期借款",
            "应付账款",
            "应交税费",
            "长期借款",
            "负债合计"
        ]
        
        # 所有者权益类关键字段
        equity_fields = [
            "实收资本",
            "资本公积",
            "盈余公积",
            "未分配利润",
            "所有者权益合计"
        ]
        
        # 提取数据
        for row in table_data.data:
            if len(row) >= 2:
                item = str(row[0]).strip() if row[0] else ""
                
                # 提取金额（期末余额）
                value = str(row[1]).strip() if len(row) > 1 and row[1] else "0"
                
                # 转换为数值
                try:
                    value = float(value)
                except ValueError:
                    value = 0
                
                # 分类存储数据
                for field in asset_fields:
                    if field in item:
                        result["assets"][field] = value
                        break
                        
                for field in liability_fields:
                    if field in item:
                        result["liabilities"][field] = value
                        break
                        
                for field in equity_fields:
                    if field in item:
                        result["equity"][field] = value
                        break
        
        return result
    
    def _process_income_statement(self, table_data: TableData) -> Dict[str, Any]:
        """处理利润表
        
        Args:
            table_data: 表格数据
            
        Returns:
            处理后的数据
        """
        result = {}
        
        if not table_data or not table_data.data:
            return result
        
        # 关键字段
        key_fields = [
            "营业收入",
            "营业成本",
            "税金及附加",
            "销售费用",
            "管理费用",
            "财务费用",
            "营业利润",
            "利润总额",
            "所得税费用",
            "净利润"
        ]
        
        # 提取数据
        for row in table_data.data:
            if len(row) >= 2:  # 项目、本期金额
                item = str(row[0]).strip() if row[0] else ""
                
                # 查找关键字段
                for field in key_fields:
                    if field in item:
                        # 提取本期金额
                        current_value = str(row[1]).strip() if len(row) > 1 and row[1] else "0"
                        # 提取上期金额（如果有）
                        previous_value = str(row[2]).strip() if len(row) > 2 and row[2] else "0"
                        
                        # 转换为数值
                        try:
                            current_value = float(current_value)
                        except ValueError:
                            current_value = 0
                            
                        try:
                            previous_value = float(previous_value)
                        except ValueError:
                            previous_value = 0
                        
                        # 存储数据
                        result[field] = {
                            "current": current_value,
                            "previous": previous_value
                        }
                        break
        
        return result
    
    def add_custom_rule(self, rule: TableRule) -> None:
        """添加自定义规则
        
        Args:
            rule: 规则对象
        """
        # 检查规则ID是否已存在
        for existing_rule in self.rules:
            if existing_rule.id == rule.id:
                # 更新现有规则
                self.rules.remove(existing_rule)
                break
        
        # 添加新规则
        self.rules.append(rule)
        logger.info(f"添加自定义规则: {rule.id} - {rule.name}")
    
    def remove_rule(self, rule_id: str) -> bool:
        """移除规则
        
        Args:
            rule_id: 规则ID
            
        Returns:
            是否成功移除
        """
        for rule in self.rules:
            if rule.id == rule_id:
                self.rules.remove(rule)
                logger.info(f"移除规则: {rule_id}")
                return True
        
        logger.warning(f"规则不存在: {rule_id}")
        return False
    
    def get_all_rules(self) -> List[TableRule]:
        """获取所有规则
        
        Returns:
            规则列表
        """
        return self.rules
    
    def get_rule_by_id(self, rule_id: str) -> Optional[TableRule]:
        """根据ID获取规则
        
        Args:
            rule_id: 规则ID
            
        Returns:
            规则对象或None
        """
        for rule in self.rules:
            if rule.id == rule_id:
                return rule
        
        return None